home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Pascal / Snippets / SCSI / scsi.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-01  |  26.1 KB  |  1,191 lines  |  [TEXT/KAHL]

  1. #include <stdio.h>
  2. #include <SCSI.h>
  3.  
  4.  
  5.  
  6. enum    { 
  7.             RETRYEXPIRE = 1, SHORTRESPLENGTH
  8.         };
  9.  
  10. #define kVendorIDSize 8
  11. #define kProductIDSize 16
  12. #define kRevisionSize 4
  13.  
  14. #define SCSICmd_TestUnitReady 0x00
  15. #define SCSICmd_Format 0x04
  16. #define SCSICmd_Read 0x08
  17. #define SCSICmd_Write 0x0A
  18. #define SCSICmd_Inquiry 0x12
  19. #define SCSICmd_ReadCap 0x25
  20. #define SCSICmd_Mode 0x15
  21. #define SCSICmd_SendDiagnostic 0x1D
  22. #define SCSICmd_ReceiveDiagnostic 0x1C
  23. #define SCSICmd_RequestSense 0x03
  24. #define SCSICmd_RezeroUnit 0x01
  25.  
  26.  
  27. #define kIOTimeout (60 * 60) /* a full minute for I/O operations */
  28. #define kFormatTimeout (60 * 60 * 60) /* an hour for formatting */
  29. #define kShortTimeout (1 * 60) /* one second for commands that we know are easy */
  30.  
  31. #define kDoWrite true
  32. #define kDoRead false
  33. #define kDoBlind true
  34. #define kDoPolled false
  35. #define kHoldIt true
  36. #define kUnholdIt false
  37. #define kIgnored false
  38. #define kNoBuffer NULL, 0, 0, kIgnored, kIgnored
  39. #define kNoLoop 0
  40.  
  41.  
  42.  
  43.  
  44. typedef short SCSIAddress;
  45. typedef unsigned char SCSICommandBlock[6];
  46.  
  47.  
  48. typedef struct SCSIResponseBlock 
  49. {    // see ANSI SCSI standard for more info about these fields
  50.         unsigned char fDeviceType;                    // these two fields indentify the device currently 
  51.         unsigned char fDeviceQualifier;                // connected to the logical unit
  52.         unsigned char fVersion;                        // this defines the version level (vendor + standard)
  53.         unsigned char fResponseFormat;                // defines the used data format (SCSI INQUIRY or something else)        
  54.         unsigned char fAdditionalLength;            // length of bytes of the parameters
  55.         unsigned char fVendorUse1;                    // vendor specific data
  56.         unsigned short fReserved1;
  57.         unsigned char fVendorID[kVendorIDSize];        // vendor ID data
  58.         unsigned char fProductID[kProductIDSize];    // product data
  59.         unsigned char fRevision[kRevisionSize];        // product version data
  60.         unsigned char fVendorUse2[20];                // vendor specific data
  61.         unsigned char fReserved2[42];
  62.         unsigned char fVendorUse3[158];                // vendor specific data
  63. };
  64.  
  65.     
  66. typedef struct SCSIResponseBlock SCSIResponseBlock;
  67.  
  68.  
  69. typedef struct SCSIModeBlock 
  70. {
  71.         unsigned char        reserved1;
  72.         unsigned char        mediumType;
  73.         unsigned char        reserved2;
  74.         unsigned char        descLength;
  75.         unsigned char        descriptor[8];
  76.         unsigned char        pageDescriptor;
  77.         unsigned char        pageLength;
  78.         unsigned char        opParams;
  79.         unsigned char        devTypeQualifier;
  80. };
  81.  
  82.     
  83. typedef struct SCSIModeBlock SCSIModeBlock;
  84.  
  85.  
  86.  
  87.  
  88.  
  89.  
  90. typedef struct SCSIFormatBlock
  91. {
  92.     unsigned char    reserved1;
  93.     unsigned char    formatOptions;
  94.     unsigned char    defectListMSB;
  95.     unsigned char    defectListLSB;
  96. };
  97.  
  98. typedef struct SCSIFormatBlock SCSIFormatBlock;
  99.  
  100.  
  101.  
  102.  
  103.  
  104.  
  105. typedef struct SCSIReqSenseBlock
  106. {
  107.     unsigned char    errorCode;
  108.     unsigned char    segNum;
  109.     unsigned char    senseKey;
  110.     unsigned char    infoMSB;
  111.     unsigned char    infoLSB;
  112.     unsigned char    senseLength;
  113.     unsigned char    commandInfoMSB;
  114.     unsigned char    commandInfoLSB;
  115.     unsigned char    senseCode;
  116.     unsigned char    senseQualifier;
  117.     unsigned char    unitCode;
  118.     unsigned char    keySpecific1;
  119.     unsigned char    keySpecific2;
  120.     unsigned char    keySpecific3;
  121. };
  122.  
  123. typedef struct SCSIReqSenseBlock SCSIReqSenseBlock;
  124.  
  125.  
  126.  
  127. typedef struct DeviceDescriptorMap
  128. {
  129.     unsigned int    sbSig;
  130.     unsigned int    sbBlockSize;
  131.     unsigned long    sbBlkCount;
  132.     unsigned int    sbDevType;
  133.     unsigned int    sbDevID;
  134.     unsigned long    sbData;
  135.     unsigned int    sbDrvrCount;
  136.     
  137.     unsigned long    ddBlock1;
  138.     unsigned int    ddSize1;
  139.     unsigned int    ddType1;
  140.     
  141.     unsigned long    ddBlock2;
  142.     unsigned int    ddSize2;
  143.     unsigned int    ddType2;
  144.     
  145.     unsigned long    ddBlock3;
  146.     unsigned int    ddSize3;
  147.     unsigned int    ddType3;
  148.     
  149.     unsigned long    ddBlock4;
  150.     unsigned int    ddSize4;
  151.     unsigned int    ddType4;
  152. };
  153.  
  154. typedef struct DeviceDescriptorMap DeviceDescriptorMap;
  155.  
  156.  
  157.  
  158. typedef struct OldPartitionMap
  159. {
  160.     unsigned int    pdSig;
  161.     
  162.     unsigned long    pdStart1;
  163.     unsigned long    pdSize1;
  164.     unsigned long    pdFSID1;
  165.     
  166.     unsigned long    pdStart2;
  167.     unsigned long    pdSize2;
  168.     unsigned long    pdFSID2;
  169.     
  170.     unsigned long    pdStart3;
  171.     unsigned long    pdSize3;
  172.     unsigned long    pdFSID3;
  173.     
  174.     unsigned long    pdStart4;
  175.     unsigned long    pdSize4;
  176.     unsigned long    pdFSID4;
  177.     
  178.     unsigned long    pdStart5;
  179.     unsigned long    pdSize5;
  180.     unsigned long    pdFSID5;
  181. };
  182.  
  183. typedef struct OldPartitionMap OldPartitionMap;
  184.  
  185. typedef SCSIInstr TransferInstructionBlock[];
  186.  
  187.  
  188.  
  189.  
  190.  
  191.  
  192. char    errorMessage[256];
  193.  
  194. OSErr CheckSCSIDevice(SCSIAddress device);
  195. OSErr SCSIDoInquiryCommand(SCSIAddress device);
  196. void StuffSCSICommandBlock(SCSICommandBlock cmd, unsigned char a, unsigned char b,unsigned char c, unsigned char d, unsigned char e, unsigned char f);
  197. OSErr SCSIOp(SCSICommandBlock cmd, short cmdSize, SCSIAddress targetSCSIID, unsigned long completionTimeout, void *buffer, unsigned long blockSize, unsigned long loopCount, Boolean writing, Boolean blind);
  198. OSErr SetDeviceMode(SCSIAddress device);
  199. OSErr PerformDiagnostic(SCSIAddress device);
  200. OSErr FormatDevice(SCSIAddress device);
  201. void ZeroStructure(Ptr theStruct,long structSize);
  202. OSErr WriteDevicePartition(SCSIAddress device);
  203. OSErr ReadDevicePartition(SCSIAddress device);
  204. OSErr BorrowBlocks(SCSIAddress device);
  205.  
  206.  
  207.  
  208. void StuffSCSICommandBlock(SCSICommandBlock cmd, unsigned char a, unsigned char b,unsigned char c, unsigned char d, unsigned char e, unsigned char f)
  209. {
  210.     cmd[0] = a;
  211.     cmd[1] = b;
  212.     cmd[2] = c;
  213.     cmd[3] = d;
  214.     cmd[4] = e;
  215.     cmd[5] = f;
  216. }
  217.  
  218.  
  219.  
  220. void StuffTransferInstructionBlock(TransferInstructionBlock tib, void *buffer, unsigned long blockSize, unsigned long loopCount)
  221. {
  222. register SCSIInstr *instr;
  223.     
  224.     
  225.     instr = tib;
  226.     
  227.     instr->scOpcode = scInc;
  228.     
  229.     instr->scParam1 = (unsigned long) buffer;
  230.     
  231.     (instr++)->scParam2 = blockSize;
  232.     
  233.     if (loopCount != 0)
  234.     {
  235.         instr->scOpcode = scLoop;
  236.         instr->scParam1 = - sizeof(SCSIInstr);
  237.         (instr++)->scParam2 = loopCount;
  238.     }
  239.     
  240.     instr->scOpcode = scStop;
  241.     
  242.     instr->scParam1 = 0;
  243.     instr->scParam2 = 0;
  244. }
  245.  
  246.  
  247.  
  248.  
  249.  
  250. OSErr SCSITestUnitReady(SCSIAddress device)
  251. {
  252. OSErr                 errCode;
  253. short                retries;
  254. SCSICommandBlock     testCmd;
  255.     
  256.     
  257.     errCode = noErr;
  258.     
  259.     StuffSCSICommandBlock(testCmd, SCSICmd_TestUnitReady, 0, 0, 0, 0, 0);
  260.     
  261.     retries = 3;
  262.     
  263.     do 
  264.     {
  265.         errCode = SCSIOp(testCmd, sizeof(SCSICommandBlock), device, kShortTimeout,NULL, 0, 0, kIgnored, kIgnored);
  266.         
  267.         if (errCode == noErr)
  268.         {
  269.             goto EXITPOINT;
  270.         }
  271.         
  272.         retries--;
  273.         
  274.     } while (retries > 0);
  275.     
  276.     
  277.     if (retries <= 0)
  278.     {
  279.         sprintf(errorMessage,"SCSITestUnitReady: retry count expired without response");
  280.         errCode = RETRYEXPIRE;
  281.         goto EXITPOINT;
  282.     }
  283.     
  284.  
  285. EXITPOINT:
  286.  
  287.     return(errCode);
  288. }
  289.  
  290.  
  291.  
  292.  
  293.  
  294. OSErr SCSIDoInquiryCommand(SCSIAddress device)
  295. {
  296. OSErr                errCode;
  297. SCSICommandBlock     inquiryCmdBlock;
  298. SCSIResponseBlock    inquiryResponse;
  299. short                 minLength;
  300. int                    i;
  301.  
  302.  
  303.     errCode = noErr;
  304.  
  305.     ZeroStructure((Ptr) &inquiryResponse, sizeof(inquiryResponse));
  306.     
  307.     minLength = (int) ((long) &(inquiryResponse.fProductID) - (long) &(inquiryResponse.fDeviceType));
  308.         
  309.     
  310.     StuffSCSICommandBlock(inquiryCmdBlock, SCSICmd_Inquiry, 0, 0, 0, 5, 0);
  311.     
  312.     errCode = SCSIOp(inquiryCmdBlock, sizeof(SCSICommandBlock), device, kShortTimeout, &inquiryResponse, 5, kNoLoop, kDoRead, kDoPolled);
  313.     
  314.     printf("inquiryResponse.fAdditionalLength + 4 = %d, displayed data includes chars 0-%d\n\n",(int) (inquiryResponse.fAdditionalLength + 4),(int) ((long) &(inquiryResponse.fVendorUse2) - (long) &(inquiryResponse.fDeviceType) - 1));
  315.     
  316.     
  317.     if (inquiryResponse.fAdditionalLength < minLength)
  318.     {
  319.         sprintf(errorMessage,"SCSIDoInquiryCommand: inquiryResponse.fAdditionalLength = %d, expected %d",(int) (inquiryResponse.fAdditionalLength),(int) minLength);
  320.         errCode = SHORTRESPLENGTH;
  321.         goto EXITPOINT;
  322.     }
  323.     
  324.     if ((errCode != noErr) || (inquiryResponse.fAdditionalLength < minLength))  
  325.         goto EXITPOINT;
  326.     
  327.     
  328.     StuffSCSICommandBlock(inquiryCmdBlock, SCSICmd_Inquiry, 0, 0, 0, inquiryResponse.fAdditionalLength, 0);
  329.     
  330.     errCode = SCSIOp(inquiryCmdBlock, sizeof(SCSICommandBlock), device, kShortTimeout, &inquiryResponse, inquiryResponse.fAdditionalLength, kNoLoop, kDoRead, kDoPolled);
  331.     
  332.     if (errCode != noErr)
  333.         goto EXITPOINT;
  334.     
  335.     
  336.     
  337.     printf("Peripheral Qualifier = 0x%02X : ",(int) (inquiryResponse.fDeviceType >> 5));
  338.     
  339.     switch (inquiryResponse.fDeviceType >> 5)
  340.     {
  341.         case 0:
  342.             printf("device connected\n");
  343.             break;
  344.         
  345.         case 1:
  346.             printf("device not currently connected\n");
  347.             break;
  348.             
  349.         case 2:
  350.             printf("Reserved\n");
  351.             break;
  352.         
  353.         case 3:
  354.             printf("unsupported device\n");
  355.             break;
  356.             
  357.         default:
  358.             printf("vendor specific\n");
  359.             break;
  360.     } 
  361.     
  362.     
  363.     printf("Peripheral Device Type = 0x%02X : ",(int) (inquiryResponse.fDeviceType & 0x1F));
  364.     
  365.     switch(inquiryResponse.fDeviceType & 0x1F)
  366.     {
  367.         case 0:
  368.             printf("direct access device\n");
  369.             break;
  370.         
  371.         case 5:
  372.             printf("CD ROM device\n");
  373.             break;
  374.         
  375.         default:
  376.             printf("other device\n");
  377.             break;
  378.     }
  379.     
  380.     
  381.     if (inquiryResponse.fDeviceQualifier & 0x80)
  382.     {
  383.         printf("Device Qualifier RMB = removable media\n");
  384.     }
  385.     
  386.     else
  387.     {
  388.         printf("Device Qualifier RMB = non-removable media\n");
  389.     }
  390.     
  391.     
  392.     printf("Vendor ID: ");
  393.     
  394.     for (i=0;i<kVendorIDSize;i++)
  395.         printf("%c",inquiryResponse.fVendorID[i]);
  396.         
  397.     printf("\n");
  398.     
  399.     
  400.     printf("Product ID: ");
  401.     
  402.     for (i=0;i<kProductIDSize;i++)
  403.         printf("%c",inquiryResponse.fProductID[i]);
  404.         
  405.     printf("\n");
  406.     
  407.     
  408.     printf("Product ID: ");
  409.     
  410.     for (i=0;i<kRevisionSize;i++)
  411.         printf("%c",inquiryResponse.fRevision[i]);
  412.         
  413.     printf("\n");
  414.     
  415.     
  416. EXITPOINT:
  417.  
  418.     return(errCode);
  419. }
  420.  
  421.  
  422.  
  423.  
  424.  
  425. OSErr SetDeviceMode(SCSIAddress device)
  426. {
  427. OSErr                errCode;
  428. SCSICommandBlock     modeCmdBlock;
  429. SCSIModeBlock        modeDataBlock;
  430. int                    i;
  431.  
  432.     errCode = noErr;
  433.     
  434.     StuffSCSICommandBlock(modeCmdBlock, SCSICmd_Mode, 0, 0, 0, 16, 0);
  435.     
  436.     modeDataBlock.reserved1 = 0x00;
  437.     modeDataBlock.mediumType = 0x00;
  438.     modeDataBlock.reserved2 = 0x00;
  439.     modeDataBlock.descLength = 0x08;
  440.     
  441.     for (i=0;i<8;i++)
  442.         modeDataBlock.descriptor[i] = 0x00;
  443.     
  444.     modeDataBlock.pageDescriptor = 0x00;
  445.     modeDataBlock.pageLength = 0x02;
  446.     modeDataBlock.opParams = 0x10;
  447.     modeDataBlock.devTypeQualifier = 0x00;
  448.     
  449.     errCode = SCSIOp(modeCmdBlock, sizeof(SCSICommandBlock), device, kShortTimeout, &modeDataBlock, sizeof(SCSIModeBlock), kNoLoop, kDoWrite, kDoPolled);
  450.     
  451.     return(errCode);
  452. }
  453.  
  454.  
  455.  
  456.  
  457.  
  458. OSErr CheckSCSIDevice(SCSIAddress device) 
  459. {
  460. OSErr errCode = noErr;
  461.  
  462.     errCode = SCSITestUnitReady(device);
  463.     
  464.     if (errCode != noErr)
  465.         goto EXITPOINT;
  466.         
  467.     errCode = SCSIDoInquiryCommand(device);
  468.     
  469. EXITPOINT:
  470.  
  471.     return(errCode);
  472. }
  473.  
  474.  
  475.  
  476.  
  477.  
  478.  
  479. OSErr SCSIOp(SCSICommandBlock cmd, short cmdSize, SCSIAddress targetSCSIID, unsigned long completionTimeout, void *buffer, unsigned long blockSize, unsigned long loopCount, Boolean writing, Boolean blind)
  480. {
  481. SCSIInstr    tib[3];
  482. short         status, message;
  483. OSErr         errCode;
  484. char        gotBus;
  485.  
  486.  
  487.     gotBus = false;
  488.     errCode = noErr;
  489.     
  490.     
  491.     if (buffer != NULL)
  492.         StuffTransferInstructionBlock(tib, buffer, blockSize, loopCount);
  493.     
  494.     
  495.     errCode = SCSIGet();
  496.     
  497.     if (errCode != noErr) 
  498.     {
  499.         sprintf(errorMessage,"SCSIOp: SCSIGet() error %d",errCode);
  500.         goto EXITPOINT;
  501.     }
  502.     
  503.     gotBus = true;
  504.     
  505.     errCode = SCSISelect(targetSCSIID);
  506.     
  507.     if (errCode != noErr)
  508.     {
  509.         sprintf(errorMessage,"SCSIOp: SCSISelect(%d) error %d",(int) (targetSCSIID),errCode);
  510.         goto EXITPOINT;
  511.     }
  512.     
  513.     
  514.     errCode = SCSICmd((Ptr) cmd, cmdSize);
  515.     
  516.     if (errCode != noErr)
  517.     {
  518.         sprintf(errorMessage,"SCSIOp: SCSICmd() error %d",errCode);
  519.         goto EXITPOINT;
  520.     }
  521.     
  522.     if (buffer != NULL)
  523.     {
  524.         if (writing)
  525.         {
  526.             if (blind)
  527.             {
  528.                 errCode = SCSIWBlind((Ptr) tib);
  529.                 
  530.                 if (errCode != noErr)
  531.                 {
  532.                     sprintf(errorMessage,"SCSIOp: SCSIWBlind() error %d",errCode);
  533.                     goto EXITPOINT;
  534.                 }
  535.             }
  536.             
  537.             else
  538.             {
  539.                 errCode = SCSIWrite((Ptr) tib);
  540.                 
  541.                 if (errCode != noErr)
  542.                 {
  543.                     sprintf(errorMessage,"SCSIOp: SCSIWrite() error %d",errCode);
  544.                     goto EXITPOINT;
  545.                 }
  546.             }
  547.         }
  548.         
  549.         else
  550.         {
  551.             if (blind)
  552.             {
  553.                 errCode = SCSIRBlind((Ptr) tib);
  554.                 
  555.                 if (errCode != noErr)
  556.                 {
  557.                     sprintf(errorMessage,"SCSIOp: SCSIRBlind() error %d",errCode);
  558.                     goto EXITPOINT;
  559.                 }
  560.             }
  561.             
  562.             else
  563.             {
  564.                 errCode = SCSIRead((Ptr) tib);
  565.                 
  566.                 if (errCode != noErr)
  567.                 {
  568.                     sprintf(errorMessage,"SCSIOp: SCSIRead() error %d",errCode);
  569.                     goto EXITPOINT;
  570.                 }
  571.             }
  572.         }
  573.     }
  574.     
  575.     
  576. EXITPOINT:
  577.     
  578.     if (gotBus)
  579.     {
  580.         if (errCode == noErr)
  581.         {
  582.             errCode = SCSIComplete(&status, &message, completionTimeout);
  583.             
  584.             if (errCode != noErr)
  585.             {
  586.                 sprintf(errorMessage,"SCSIOp: SCSIComplete() error %d",errCode);
  587.             }
  588.         }
  589.         
  590.         else
  591.             SCSIComplete(&status, &message, completionTimeout);
  592.     }
  593.  
  594.  
  595.     //    Attempt to return the most valuable result possible.  A SCSI Manager error is
  596.     //    negated to distinguish it from a positive SCSI status byte code, which may be
  597.     //    returned for a failed transaction even if the SCSI Manager is "successful."
  598.     //
  599.     //    If there were no errors from the SCSI Manager, the result is the SCSI status
  600.     //    byte, otherwise it is the negation of the SCSI Manager error.
  601.     //
  602.     
  603.     if (errCode == noErr)
  604.     {
  605.         sprintf(errorMessage,"SCSIOp: device returned status = %d, message = %d",(int) status,(int) message);
  606.         
  607.         return(status);
  608.     }
  609.     
  610.     else
  611.         return(errCode);
  612. }
  613.  
  614.  
  615.  
  616.  
  617. OSErr FormatDevice(SCSIAddress device)
  618. {
  619. OSErr                errCode;
  620. SCSICommandBlock     formatCmdBlock;
  621.  
  622.     errCode = noErr;
  623.     
  624.     StuffSCSICommandBlock(formatCmdBlock, SCSICmd_Format, 0, 0, 0, 0x03, 0);
  625.     
  626.     errCode = SCSIOp(formatCmdBlock, sizeof(SCSICommandBlock), device, kFormatTimeout, NULL, 0, 0, kIgnored, kIgnored);
  627.     
  628.     return(errCode);
  629. }
  630.  
  631.  
  632.  
  633.  
  634. OSErr PerformDiagnostic(SCSIAddress device)
  635. {
  636. OSErr                errCode;
  637. SCSICommandBlock     sendDiagnosticCmdBlock;
  638. SCSICommandBlock     receiveDiagnosticCmdBlock;
  639.  
  640.     errCode = noErr;
  641.     
  642.     StuffSCSICommandBlock(sendDiagnosticCmdBlock, SCSICmd_SendDiagnostic, 0x04, 0, 0, 0, 0x01);
  643.     
  644.     errCode = SCSIOp(sendDiagnosticCmdBlock, sizeof(SCSICommandBlock), device, kFormatTimeout, NULL, 0, 0, kIgnored, kIgnored);
  645.     
  646.     if (errCode != noErr)
  647.         goto EXITPOINT;
  648.  
  649.  
  650.     StuffSCSICommandBlock(receiveDiagnosticCmdBlock, SCSICmd_ReceiveDiagnostic, 0x04, 0, 0, 0, 0);
  651.     
  652.     errCode = SCSIOp(receiveDiagnosticCmdBlock, sizeof(SCSICommandBlock), device, kFormatTimeout, NULL, 0, 0, kIgnored, kIgnored);
  653.     
  654.     if (errCode != noErr)
  655.         goto EXITPOINT;
  656.         
  657. EXITPOINT:
  658.  
  659.     return(errCode);
  660. }
  661.  
  662.  
  663.  
  664.  
  665.  
  666. OSErr CheckDeviceCondition(SCSIAddress device)
  667. {
  668. OSErr                errCode;
  669. SCSICommandBlock     checkConditionCmdBlock;
  670. SCSIReqSenseBlock    reqSenseDataBlock;
  671.  
  672.     errCode = noErr;
  673.     
  674.     ZeroStructure((Ptr) &reqSenseDataBlock, sizeof(reqSenseDataBlock));
  675.     
  676.     StuffSCSICommandBlock(checkConditionCmdBlock, SCSICmd_RequestSense, 0, 0, 0, sizeof(SCSIReqSenseBlock), 0);
  677.     
  678.     errCode = SCSIOp(checkConditionCmdBlock, sizeof(SCSICommandBlock), device, kIOTimeout, &reqSenseDataBlock, sizeof(SCSIReqSenseBlock), kNoLoop, kDoRead, kDoPolled);
  679.     
  680.     if (errCode != noErr)
  681.         goto EXITPOINT;
  682.  
  683.     printf("\n\n");
  684.     
  685.     if (reqSenseDataBlock.errorCode & 0x80 == 0)
  686.         printf("Uh oh-- reqSenseDataBlock.errorCode & 0x80 == 0, returned sense data is probably invalid\n\n");
  687.     
  688.     printf("errorCode = 0x%02X\n",(int) (reqSenseDataBlock.errorCode & 0x7F));
  689.     
  690.     printf("segment number = 0x%02X\n",(int) (reqSenseDataBlock.segNum));
  691.     
  692.     printf("filemark = 0x%02X\n",(int) ((reqSenseDataBlock.senseKey & 0x80) >> 7));
  693.     
  694.     printf("EOM = 0x%02X\n",(int) ((reqSenseDataBlock.senseKey & 0x40) >> 6));
  695.     printf("ILI = 0x%02X\n",(int) ((reqSenseDataBlock.senseKey & 0x20) >> 5));
  696.     
  697.     printf("sense key = 0x%02X\n",(int) (reqSenseDataBlock.senseKey & 0x07));
  698.     
  699.     printf("information = 0x%04X\n",(unsigned int) ((unsigned int) reqSenseDataBlock.infoMSB) * 256 + ((unsigned int) reqSenseDataBlock.infoLSB));
  700.     
  701.     printf("additional sense length = 0x%02X\n",(int) (reqSenseDataBlock.senseLength));
  702.     
  703.     printf("command-specific information = 0x%04X\n",(unsigned int) ((unsigned int) reqSenseDataBlock.commandInfoMSB) * 256 + ((unsigned int) reqSenseDataBlock.commandInfoLSB));
  704.     
  705.     printf("additional sense code = 0x%02X\n",(int) (reqSenseDataBlock.senseCode));
  706.     
  707.     printf("additional sense code qualifier = 0x%02X\n",(int) (reqSenseDataBlock.senseQualifier));
  708.     
  709.     printf("unit code = 0x%02X\n",(int) (reqSenseDataBlock.unitCode));
  710.     
  711.     if ((reqSenseDataBlock.senseKey & 0x07) == 0x05)
  712.     {
  713.         printf("SKSV = 0x%02X\n",(int) ((reqSenseDataBlock.keySpecific1 & 0x80) >> 7));
  714.         printf("C/D = 0x%02X\n",(int) ((reqSenseDataBlock.keySpecific1 & 0x40) >> 6));
  715.         printf("BPV = 0x%02X\n",(int) ((reqSenseDataBlock.keySpecific1 & 0x08) >> 3));
  716.         printf("bit pointer = 0x%02X\n",(int) (reqSenseDataBlock.keySpecific1 & 0x07));
  717.     }
  718.     
  719.     else if ((reqSenseDataBlock.senseKey & 0x07) == 0x02)
  720.     {
  721.         printf("SKSV = 0x%02X\n",(int) ((reqSenseDataBlock.keySpecific1 & 0x80) >> 7));
  722.         printf("progress = 0x%04X\n",(unsigned int) ((unsigned int) reqSenseDataBlock.keySpecific2) * 256 + ((unsigned int) reqSenseDataBlock.keySpecific3));
  723.     }
  724.     
  725.     else if (((reqSenseDataBlock.senseKey & 0x07) == 1) ||
  726.             ((reqSenseDataBlock.senseKey & 0x07) == 4) ||
  727.             ((reqSenseDataBlock.senseKey & 0x07) == 3))
  728.     {
  729.         printf("SKSV = 0x%02X\n",(int) ((reqSenseDataBlock.keySpecific1 & 0x80) >> 7));
  730.         printf("actual retry count = 0x%04X\n",(unsigned int) ((unsigned int) reqSenseDataBlock.keySpecific2) * 256 + ((unsigned int) reqSenseDataBlock.keySpecific3));
  731.     }
  732.     
  733. EXITPOINT:
  734.     
  735.     return(errCode);
  736. }
  737.  
  738.  
  739.  
  740.  
  741. void ZeroStructure(Ptr theStruct,long structSize)
  742. {
  743. register char     *ch;
  744. register long    ci;
  745.  
  746.     if (theStruct)
  747.     {
  748.         ch = (char *) theStruct;
  749.         ci = structSize;
  750.         
  751.         while (ci--)
  752.             *ch = 0x00;
  753.     }
  754. }
  755.  
  756.  
  757.  
  758.  
  759. OSErr WriteDevicePartition(SCSIAddress device)
  760. {
  761. OSErr                errCode;
  762. SCSICommandBlock     writeCmdBlock;
  763. DeviceDescriptorMap    ddMap;
  764. OldPartitionMap        partitionMap;
  765.  
  766.     errCode = noErr;
  767.     
  768.     ddMap.sbSig = 0x4552;
  769.     ddMap.sbBlockSize = 512;
  770.     ddMap.sbBlkCount = 40000L;
  771.     ddMap.sbDevType = 0;
  772.     ddMap.sbDevID = 0;
  773.     ddMap.sbData = 0;
  774.     ddMap.sbDrvrCount = 1;
  775.     ddMap.ddBlock1 = 2;
  776.     ddMap.ddSize1 = 3;
  777.     ddMap.ddType1 = 1;
  778.     ddMap.ddBlock2 = 0;
  779.     ddMap.ddSize2 = 0;
  780.     ddMap.ddType2 = 0;
  781.     
  782.     
  783.     StuffSCSICommandBlock(writeCmdBlock, SCSICmd_Write, 0, 0, 0, 0x01, 0);
  784.     
  785.     errCode = SCSIOp(writeCmdBlock, sizeof(SCSICommandBlock), device, kIOTimeout, &ddMap, 512, kNoLoop, kDoWrite, kDoPolled);
  786.     
  787.     if (errCode != noErr)
  788.     {
  789.         errCode = CheckDeviceCondition(device);
  790.         
  791.         if (errCode != noErr)
  792.             printf("%s\n",errorMessage);
  793.     }
  794.  
  795.     partitionMap.pdSig = 0x5453;
  796.     
  797.     partitionMap.pdStart1 = 0;
  798.     partitionMap.pdSize1 = 1;
  799.     partitionMap.pdFSID1 = 'ddmp';
  800.     
  801.     partitionMap.pdStart2 = 2;
  802.     partitionMap.pdSize2 = 1;
  803.     partitionMap.pdFSID2 = 'dpmp';
  804.     
  805.     partitionMap.pdStart3 = 3;
  806.     partitionMap.pdSize3 = 5;
  807.     partitionMap.pdFSID3 = 'drvr';
  808.     
  809.     partitionMap.pdStart4 = 8;
  810.     partitionMap.pdSize4 = 40000L - 8;
  811.     partitionMap.pdFSID4 = 'TFS1';
  812.     
  813.     partitionMap.pdStart5 = 0;
  814.     partitionMap.pdSize5 = 0;
  815.     partitionMap.pdFSID5 = 0;
  816.     
  817.     
  818.     StuffSCSICommandBlock(writeCmdBlock, SCSICmd_Write, 0, 0, 1, 0x01, 0);
  819.     
  820.     errCode = SCSIOp(writeCmdBlock, sizeof(SCSICommandBlock), device, kIOTimeout, &partitionMap, 512, kNoLoop, kDoWrite, kDoPolled);
  821.     
  822.     if (errCode != noErr)
  823.     {
  824.         errCode = CheckDeviceCondition(device);
  825.         
  826.         if (errCode != noErr)
  827.             printf("%s\n",errorMessage);
  828.     }
  829.  
  830. EXITPOINT:
  831.  
  832.     return(errCode);
  833. }
  834.  
  835.  
  836.  
  837.  
  838.  
  839. OSErr ReadDevicePartition(SCSIAddress device)
  840. {
  841. OSErr                errCode;
  842. SCSICommandBlock     readCmdBlock;
  843. DeviceDescriptorMap    *ddMap;
  844. OldPartitionMap        *partitionMap;
  845. char                buffer[512];
  846.  
  847.     errCode = noErr;
  848.     
  849.     ddMap = (DeviceDescriptorMap *) &buffer;
  850.     partitionMap = (OldPartitionMap *) &buffer;
  851.     
  852.     StuffSCSICommandBlock(readCmdBlock, SCSICmd_Read, 0, 0, 0, 0x01, 0);
  853.     
  854.     errCode = SCSIOp(readCmdBlock, sizeof(SCSICommandBlock), device, kIOTimeout, &buffer, 512, kNoLoop, kDoRead, kDoPolled);
  855.     
  856.     if (errCode != noErr)
  857.     {
  858.         errCode = CheckDeviceCondition(device);
  859.         
  860.         if (errCode != noErr)
  861.             printf("%s\n",errorMessage);
  862.     }
  863.     
  864.     printf("\Device Descriptor Map (sector 0):\n");
  865.     
  866.     printf("ddMap.sbSig = 0x%04X (should be 0x4552)\n",ddMap->sbSig);
  867.     printf("ddMap.sbBlockSize = 0x%04X\n",ddMap->sbBlockSize);
  868.     printf("ddMap.sbBlkCount = 0x%08lX\n",ddMap->sbBlkCount);
  869.     printf("ddMap.sbDevType = 0x%04X\n",ddMap->sbDevType);
  870.     printf("ddMap.sbDevID = 0x%04X\n",ddMap->sbDevID);
  871.     printf("ddMap.sbData = 0x%08lX\n",ddMap->sbData);
  872.     printf("ddMap.sbDrvrCount = 0x%04X\n",ddMap->sbDrvrCount);
  873.     
  874.     printf("ddMap.ddBlock1 = 0x%08lX\n",ddMap->ddBlock1);
  875.     printf("ddMap.ddSize1 = 0x%04X\n",ddMap->ddSize1);
  876.     printf("ddMap.ddType1 = 0x%04X\n",ddMap->ddType1);
  877.     
  878.     printf("ddMap.ddBlock2 = 0x%08lX\n",ddMap->ddBlock2);
  879.     printf("ddMap.ddSize2 = 0x%04X\n",ddMap->ddSize2);
  880.     printf("ddMap.ddType2 = 0x%04X\n",ddMap->ddType2);
  881.     
  882.     printf("ddMap.ddBlock3 = 0x%08lX\n",ddMap->ddBlock3);
  883.     printf("ddMap.ddSize3 = 0x%04X\n",ddMap->ddSize3);
  884.     printf("ddMap.ddType3 = 0x%04X\n",ddMap->ddType3);
  885.     
  886.     printf("ddMap.ddBlock4 = 0x%08lX\n",ddMap->ddBlock4);
  887.     printf("ddMap.ddSize4 = 0x%04X\n",ddMap->ddSize4);
  888.     printf("ddMap.ddType4 = 0x%04X\n",ddMap->ddType4);
  889.     
  890.     printf("\n");
  891.     
  892.     
  893.     
  894.     StuffSCSICommandBlock(readCmdBlock, SCSICmd_Read, 0, 0, 1, 0x01, 0);
  895.     
  896.     errCode = SCSIOp(readCmdBlock, sizeof(SCSICommandBlock), device, kIOTimeout, &buffer, 512, kNoLoop, kDoRead, kDoPolled);
  897.     
  898.     if (errCode != noErr)
  899.     {
  900.         errCode = CheckDeviceCondition(device);
  901.         
  902.         if (errCode != noErr)
  903.             printf("%s\n",errorMessage);
  904.     }
  905.     
  906.     printf("\nPartition Map (sector 1): \n");
  907.     
  908.     printf("partitionMap.pdSig = 0x%04X (should be 0x5453)\n",partitionMap->pdSig);
  909.     
  910.     printf("partitionMap.pdStart1 = 0x%08lX\n",partitionMap->pdStart1);
  911.     printf("partitionMap.pdSize1 = 0x%08lX\n",partitionMap->pdSize1);
  912.     printf("partitionMap.pdFSID1 = %c%c%c%c\n",((char *) &(partitionMap->pdFSID1))[0],((char *) &(partitionMap->pdFSID1))[1],((char *) &(partitionMap->pdFSID1))[2],((char *) &(partitionMap->pdFSID1))[3]);
  913.     
  914.     printf("partitionMap.pdStart2 = 0x%08lX\n",partitionMap->pdStart2);
  915.     printf("partitionMap.pdSize2 = 0x%08lX\n",partitionMap->pdSize2);
  916.     printf("partitionMap.pdFSID2 = %c%c%c%c\n",((char *) &(partitionMap->pdFSID2))[0],((char *) &(partitionMap->pdFSID2))[1],((char *) &(partitionMap->pdFSID2))[2],((char *) &(partitionMap->pdFSID2))[3]);
  917.     
  918.     printf("partitionMap.pdStart3 = 0x%08lX\n",partitionMap->pdStart3);
  919.     printf("partitionMap.pdSize3 = 0x%08lX\n",partitionMap->pdSize3);
  920.     printf("partitionMap.pdFSID3 = %c%c%c%c\n",((char *) &(partitionMap->pdFSID3))[0],((char *) &(partitionMap->pdFSID3))[1],((char *) &(partitionMap->pdFSID3))[2],((char *) &(partitionMap->pdFSID3))[3]);
  921.     
  922.     printf("partitionMap.pdStart4 = 0x%08lX\n",partitionMap->pdStart4);
  923.     printf("partitionMap.pdSize4 = 0x%08lX\n",partitionMap->pdSize4);
  924.     printf("partitionMap.pdFSID4 = %c%c%c%c\n",((char *) &(partitionMap->pdFSID4))[0],((char *) &(partitionMap->pdFSID4))[1],((char *) &(partitionMap->pdFSID4))[2],((char *) &(partitionMap->pdFSID4))[3]);
  925.     
  926.     printf("partitionMap.pdStart5 = 0x%08lX\n",partitionMap->pdStart5);
  927.     printf("partitionMap.pdSize5 = 0x%08lX\n",partitionMap->pdSize5);
  928.     printf("partitionMap.pdFSID5 = %c%c%c%c\n",((char *) &(partitionMap->pdFSID5))[0],((char *) &(partitionMap->pdFSID5))[1],((char *) &(partitionMap->pdFSID5))[2],((char *) &(partitionMap->pdFSID5))[3]);
  929.     
  930.     
  931.     printf("\n");
  932. }
  933.  
  934.  
  935.  
  936.  
  937.  
  938. OSErr BorrowBlocks(SCSIAddress device)
  939. {
  940. OSErr                errCode;
  941. SCSICommandBlock     readCmdBlock;
  942. SCSICommandBlock     writeCmdBlock;
  943. char                buffer[512];
  944. unsigned int        blockNum;
  945.  
  946.     errCode = noErr;
  947.     
  948.     for (blockNum = 0; blockNum < 255;blockNum++)
  949.     {
  950.         StuffSCSICommandBlock(readCmdBlock, SCSICmd_Read, 0, 0, blockNum, 0x01, 0);
  951.         
  952.         errCode = SCSIOp(readCmdBlock, sizeof(SCSICommandBlock), 0, kIOTimeout, &buffer, 512, kNoLoop, kDoRead, kDoPolled);
  953.         
  954.         if (errCode != noErr)
  955.         {
  956.             errCode = CheckDeviceCondition(device);
  957.             
  958.             if (errCode != noErr)
  959.                 printf("%s\n",errorMessage);
  960.             
  961.             goto EXITPOINT;
  962.         }
  963.         
  964.         
  965.         StuffSCSICommandBlock(writeCmdBlock, SCSICmd_Write, 0, 0, blockNum, 0x01, 0);
  966.         
  967.         errCode = SCSIOp(writeCmdBlock, sizeof(SCSICommandBlock), device, kIOTimeout, &buffer, 512, kNoLoop, kDoWrite, kDoPolled);
  968.         
  969.         if (errCode != noErr)
  970.         {
  971.             errCode = CheckDeviceCondition(device);
  972.             
  973.             if (errCode != noErr)
  974.                 printf("%s\n",errorMessage);
  975.             
  976.             goto EXITPOINT;
  977.         }
  978.     }
  979.     
  980.     
  981. EXITPOINT:
  982.  
  983.     return(errCode);
  984. }
  985.  
  986.  
  987.  
  988.  
  989. OSErr RezeroDevice(SCSIAddress device)
  990. {
  991. OSErr                errCode;
  992. SCSICommandBlock     rezeroCmdBlock;
  993.  
  994.     errCode = noErr;
  995.     
  996.     StuffSCSICommandBlock(rezeroCmdBlock, SCSICmd_RezeroUnit, 0, 0, 0, 0, 0);
  997.     
  998.     errCode = SCSIOp(rezeroCmdBlock, sizeof(SCSICommandBlock), device, kIOTimeout, NULL, 0, kIgnored, kIgnored, kIgnored);
  999.     
  1000.     if (errCode != noErr)
  1001.     {
  1002.         errCode = CheckDeviceCondition(device);
  1003.         
  1004.         if (errCode != noErr)
  1005.             printf("%s\n",errorMessage);
  1006.     }
  1007.  
  1008.     return(errCode);
  1009. }
  1010.  
  1011.  
  1012.  
  1013. main()
  1014. {
  1015. int        i;
  1016. OSErr    errCode;
  1017.  
  1018.     printf("SCSI.π\n\n");
  1019.     
  1020.     printf("resize window and press a key to continue\n\n");
  1021.     
  1022.     getchar();
  1023.     
  1024.     i = 6;
  1025.     
  1026.     printf("\n\n");
  1027.     
  1028.  
  1029.     printf("Rezeroing Unit\n");
  1030.     
  1031.     errCode = RezeroDevice(i);
  1032.     
  1033.     if (errCode != noErr)
  1034.         printf("%s\n",errorMessage);
  1035.     
  1036.     if (errCode == 2)
  1037.     {
  1038.         errCode = CheckDeviceCondition(i);
  1039.         
  1040.         if (errCode != noErr)
  1041.             printf("%s\n",errorMessage);
  1042.     }
  1043.     
  1044.     
  1045.     
  1046.     errCode = BorrowBlocks(i);
  1047.     
  1048.  
  1049.     printf("Setting mode for device %d\n",i);
  1050.     
  1051.     errCode = SetDeviceMode(i);
  1052.     
  1053.     if (errCode != noErr)
  1054.         printf("%s\n",errorMessage);
  1055.     
  1056.     if (errCode == 2)
  1057.     {
  1058.         errCode = CheckDeviceCondition(i);
  1059.         
  1060.         if (errCode != noErr)
  1061.             printf("%s\n",errorMessage);
  1062.     }
  1063.     
  1064.     
  1065.     
  1066.     printf("Formatting device %d\n",i);
  1067.     
  1068.     errCode = FormatDevice(i);
  1069.     
  1070.     if (errCode != noErr)
  1071.         printf("%s\n",errorMessage);
  1072.     
  1073.     if (errCode == 2)
  1074.     {
  1075.         errCode = CheckDeviceCondition(i);
  1076.         
  1077.         if (errCode != noErr)
  1078.             printf("%s\n",errorMessage);
  1079.     }
  1080.     
  1081.     
  1082.     
  1083.     
  1084.     printf("Setting mode for device %d\n",i);
  1085.     
  1086.     errCode = SetDeviceMode(i);
  1087.     
  1088.     if (errCode != noErr)
  1089.         printf("%s\n",errorMessage);
  1090.     
  1091.     if (errCode == 2)
  1092.     {
  1093.         errCode = CheckDeviceCondition(i);
  1094.         
  1095.         if (errCode != noErr)
  1096.             printf("%s\n",errorMessage);
  1097.     }
  1098.     
  1099.     
  1100.     
  1101.     printf("\n\nChecking SCSI device #%d\n\n",i);
  1102.     
  1103.     errCode = CheckSCSIDevice(i);
  1104.     
  1105.     printf("\n");
  1106.     
  1107.     if (errCode != noErr)
  1108.         printf("SCSI device #%d error: %s\n",i,errorMessage);
  1109.     
  1110.     if (errCode == 2)
  1111.     {
  1112.         errCode = CheckDeviceCondition(i);
  1113.         
  1114.         if (errCode != noErr)
  1115.             printf("%s\n",errorMessage);
  1116.     }
  1117.  
  1118.  
  1119.  
  1120.  
  1121.  
  1122.  
  1123.     printf("Rezeroing Unit\n");
  1124.     
  1125.     errCode = RezeroDevice(i);
  1126.     
  1127.     if (errCode != noErr)
  1128.         printf("%s\n",errorMessage);
  1129.     
  1130.     if (errCode == 2)
  1131.     {
  1132.         errCode = CheckDeviceCondition(i);
  1133.         
  1134.         if (errCode != noErr)
  1135.             printf("%s\n",errorMessage);
  1136.     }
  1137.     
  1138.     
  1139.     
  1140.     
  1141.     printf("\n\nWriting device descriptor and partition maps to device %d\n\n",i);
  1142.     
  1143.     errCode = WriteDevicePartition(i);
  1144.     
  1145.     printf("\n");
  1146.     
  1147.     if (errCode != noErr)
  1148.         printf("SCSI device #%d error: %s\n",i,errorMessage);
  1149.     
  1150.     if (errCode != noErr)
  1151.     {
  1152.         errCode = CheckDeviceCondition(i);
  1153.         
  1154.         if (errCode != noErr)
  1155.             printf("%s\n",errorMessage);
  1156.     }
  1157.     
  1158.     
  1159.     errCode = ReadDevicePartition(i);
  1160.     
  1161.     if (errCode != noErr)
  1162.         printf("SCSI device #%d error: %s\n",i,errorMessage);
  1163.     
  1164.     if (errCode != noErr)
  1165.     {
  1166.         errCode = CheckDeviceCondition(i);
  1167.         
  1168.         if (errCode != noErr)
  1169.             printf("%s\n",errorMessage);
  1170.     }
  1171.     
  1172.     
  1173.     
  1174.     errCode = ReadDevicePartition(0);
  1175.     
  1176.     if (errCode != noErr)
  1177.         printf("SCSI device #%d error: %s\n",i,errorMessage);
  1178.     
  1179.     if (errCode != noErr)
  1180.     {
  1181.         errCode = CheckDeviceCondition(i);
  1182.         
  1183.         if (errCode != noErr)
  1184.             printf("%s\n",errorMessage);
  1185.     }
  1186.     
  1187.     
  1188. EXITPOINT:
  1189.  
  1190.     printf("\n\nThe End.\n");
  1191. }